package role

import (
	"strconv"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"

	"github.com/super-team/start-kit/handler/response"
	"github.com/super-team/start-kit/middlewares/jwt"
	"github.com/super-team/start-kit/models"
	"github.com/super-team/start-kit/pkg/casbin"
	"github.com/super-team/start-kit/pkg/mysql"
	"github.com/super-team/start-kit/tools/log"
)

func Route(r *gin.RouterGroup, middlewares ...gin.HandlerFunc) {

	a := r.Group("/role", middlewares...)
	{
		a.POST("", addRole)
		a.PUT("", updateRole)
		a.DELETE("", deleteRole)
		a.GET("/menu", GetRoleMenu)
		a.GET("/list", getRoleList)
		a.GET("/info", getRoleInfo)
		a.PUT("/status", updateRoleStatus)
		a.GET("/simpleList", getSimpleRoleList)
	}

}

// @Summary 根据角色KEY获取菜单
// @Description 根据角色KEY获取菜单
// @Tags role
// @Accept json
// @Param Authorization header string false "Bearer 用户令牌"
// @Success 200 {string} string	"{"code": 200, "message": "获取菜单成功"}"
// @Failure 200 {string} string	"{"code": -1, "message": "获取菜单失败"}"
// @Router /api/role/menu [get]
func GetRoleMenu(ctx *gin.Context) {
	r := jwt.GetAuthRole(ctx)
	if r == nil {
		response.Error(ctx, "获取菜单失败")
		return
	}
	menus, err := models.GetMenuByRoleKey(ctx, *r.RoleKey)
	if response.ServerError(ctx, err) {
		return
	}
	response.Success(ctx, "获取菜单成功", menus)
}

type roleListRequest struct {
	PageSize  int `json:"pageSize" form:"pageSize" uri:"pageSize" binding:"required"`
	PageIndex int `json:"pageIndex" form:"pageIndex" uri:"pageIndex" binding:"required"`
}

// @Summary 角色列表数据
// @Description Get JSON
// @Tags role
// @Param Authorization header string false "Bearer 用户令牌"
// @Param pageSize query int false "页条数"
// @Param pageIndex query int false "页码"
// @Success 200 {string} string "{"code": 200, "data": [...]}"
// @Failure 200 {string} string	"{"code": -1, "message": "参数错误"}"
// @Failure 200 {string} string	"{"code": -1, "message": "暂无角色列表"}"
// @Router /api/role/list [get]
func getRoleList(ctx *gin.Context) {
	request := new(roleListRequest)
	if err := ctx.ShouldBind(request); err != nil {
		response.Error(ctx, "参数错误")
		return
	}
	roles, err := models.GetRoleList(ctx, request.PageSize, request.PageIndex)
	if response.ServerError(ctx, err) {
		return
	}
	response.Success(ctx, "获取角色列表成功", roles)
}

// @Summary 创建role
// @Description 创建role
// @Tags role
// @Accept  application/json
// @Product application/json
// @Param Authorization header string false "Bearer 用户令牌"
// @Param data body models.Role true "data"
// @Success 200 {string} string	"{"code": 200, "message": "添加角色成功"}"
// @Failure 200 {string} string	"{"code": -1, "message": "参数错误"}"
// @Failure 200 {string} string	"{"code": -1, "message": "服务器异常，请稍后再试"}"
// @Router /api/role [post]
func addRole(ctx *gin.Context) {
	role := new(models.Role)
	if err := ctx.ShouldBindJSON(role); err != nil {
		response.Error(ctx, "参数错误")
		return
	}
	menuIDs := role.MenuIds
	err := mysql.DB.Transaction(func(tx *gorm.DB) error {
		var err error
		roleID, err := models.AddRole(tx, role)
		if err != nil {
			return err
		}
		if len(menuIDs) > 0 {
			err = models.AddRoleMenu(tx, *role.RoleKey, roleID, menuIDs)
		}
		return err
	})
	if response.ServerError(ctx, err) {
		return
	}
	if err := casbin.Permission.LoadPolicy(); err != nil {
		log.Log.Err(err).Send()
	}
	response.Success(ctx, "添加角色成功", nil)
}

// @Summary 修改角色
// @Description 修改角色
// @Tags role
// @Accept  application/json
// @Product application/json
// @Param Authorization header string false "Bearer 用户令牌"
// @Param data body models.Role true "body"
// @Success 200 {string} string	"{"code": 200, "message": "修改成功"}"
// @Success 200 {string} string	"{"code": -1, "message": "修改失败"}"
// @Router /api/role [put]
func updateRole(ctx *gin.Context) {
	role := new(models.Role)
	if err := ctx.ShouldBindJSON(role); err != nil {
		response.Error(ctx, "参数错误")
		return
	}
	if role.ID == 0 {
		response.Error(ctx, "参数错误")
		return
	}
	err := mysql.DB.Transaction(func(tx *gorm.DB) error {
		var err error
		err = models.UpdateRole(tx, role)
		if err != nil {
			return err
		}
		err = models.DeleteRoleMenu(tx, int64(role.ID))
		if err != nil {
			return err
		}
		err = models.DeletePermission(tx, *role.RoleKey)
		if err != nil {
			return err
		}
		if len(role.MenuIds) > 0 {
			err = models.AddRoleMenu(tx, *role.RoleKey, int64(role.ID), role.MenuIds)
		}
		return err
	})
	if response.ServerError(ctx, err) {
		return
	}
	if err := casbin.Permission.LoadPolicy(); err != nil {
		log.Log.Err(err).Send()
	}
	response.Success(ctx, "修改角色成功", nil)
}

type deleteRequest struct {
	ID      int64  `json:"id" form:"id" uri:"id" binding:"required"`
	RoleKey string `json:"roleKey" form:"roleKey" uri:"roleKey" binding:"required"`
}

// @Summary 删除角色
// @Description 删除角色
// @Tags role
// @Accept  application/json
// @Product application/json
// @Param Authorization header string false "Bearer 用户令牌"
// @Param data body deleteRequest true "body"
// @Success 200 {string} string	"{"code": 200, "message": "删除角色成功"}"
// @Success 200 {string} string	"{"code": -1, "message": "参数错误"}"
// @Router /api/role [delete]
func deleteRole(ctx *gin.Context) {
	request := new(deleteRequest)
	if err := ctx.ShouldBind(request); err != nil {
		response.Error(ctx, "参数错误")
		return
	}
	if request.ID == 0 {
		response.Error(ctx, "参数错误")
		return
	}
	err := mysql.DB.Transaction(func(tx *gorm.DB) (err error) {
		err = models.DeleteRoleByID(tx, request.ID)
		if err != nil {
			return
		}
		err = models.DeleteRoleMenu(tx, request.ID)
		if err != nil {
			return
		}
		return models.DeletePermission(tx, request.RoleKey)
	})
	if response.ServerError(ctx, err) {
		return
	}
	if err := casbin.Permission.LoadPolicy(); err != nil {
		log.Log.Err(err).Send()
	}
	response.Success(ctx, "删除角色成功", nil)
}

// @Summary 获取Role数据
// @Description 获取Role数据
// @Tags role
// @Param Authorization header string false "Bearer 用户令牌"
// @Param roleId path string false "roleId"
// @Success 200 {string} string "{"code": 200, "data": [...]}"
// @Success 200 {string} string "{"code": -1, "message": "参数错误"}"
// @Router /api/role/info [get]
func getRoleInfo(ctx *gin.Context) {
	id := ctx.Query("id")
	idInt, err := strconv.ParseInt(id, 10, 64)
	if err != nil {
		response.Error(ctx, "参数错误")
		return
	}
	role, err := models.GetRoleByID(ctx, idInt)
	if response.ServerError(ctx, err) {
		return
	}
	response.Success(ctx, "获取角色信息成功", role)
}

type updateRoleRequest struct {
	ID     int `json:"id" binding:"required"`
	Status int `json:"status" binding:"required"`
}

// @Summary 修改角色状态
// @Description 修改角色状态
// @Tags role
// @Param Authorization header string false "Bearer 用户令牌"
// @Param data body updateRoleRequest true "body"
// @Success 200 {string} string "{"code": 200, "data": null,"message":"修改角色状态成功"}"
// @Success 200 {string} string "{"code": -1, "message": "参数错误"}"
// @Router /api/role/status [put]
func updateRoleStatus(ctx *gin.Context) {
	request := new(updateRoleRequest)
	if err := ctx.ShouldBindJSON(request); err != nil {
		response.Error(ctx, "参数错误")
		return
	}
	res := mysql.DB.WithContext(ctx).
		Table("role").Where("id = ?", request.ID).
		Update("status", request.Status)
	if response.ServerError(ctx, res.Error) {
		return
	}
	response.Success(ctx, "修改角色状态成功", nil)
}

// @Summary 获取简单角色列表
// @Description 获取简单角色列表
// @Tags role
// @Param Authorization header string false "Bearer 用户令牌"
// @Success 200 {string} string "{"code": 200, "data": [...]}"
// @Failure 200 {string} string	"{"code": -1, "message": "暂无角色列表"}"
// @Router /api/role/simpleList [get]
func getSimpleRoleList(ctx *gin.Context) {
	list, err := models.GetSimpleRoleList(ctx)
	if response.ServerError(ctx, err) {
		return
	}
	response.Success(ctx, "获取角色列表成功", list)
}
